#include "BaseWindow.h"

const TCHAR* BaseWindow::CLASS_NAME = L"JurkowskimWindow";
const TCHAR* BaseWindow::MSG_NAME = L"MsgJurkowskimWindow";

BaseWindow* single = NULL;

void BaseWindow::CreateWndClass(HICON hIcon) {
	WNDCLASSEX wcx;
	wcx.cbSize = sizeof(WNDCLASSEX);
	wcx.style = CS_DBLCLKS;
	wcx.cbClsExtra = 0;
	wcx.cbWndExtra = 0;
	wcx.hInstance = hInst;
	wcx.hIcon = hIcon;
	wcx.hCursor = LoadCursor(0, IDC_ARROW);
	wcx.hbrBackground = 0;
	wcx.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
	wcx.hIconSm = 0;
	wcx.lpszClassName = CLASS_NAME;
	wcx.lpfnWndProc = &WndProc;

	RegisterClassEx(&wcx);
}

DWORD BaseWindow::GetWindowStyle() {
	if(fullScreen)
		return WS_POPUP | WS_SYSMENU | WS_VISIBLE;
	else 
		return (WS_OVERLAPPED | WS_MINIMIZEBOX | 
			WS_THICKFRAME | WS_MAXIMIZEBOX |
			WS_CAPTION | WS_SYSMENU | WS_VISIBLE);
}

void BaseWindow::CreateWnd() {
	DWORD style = GetWindowStyle();
	RECT rc = {0, 0, wndWidth, wndHeight};
	AdjustWindowRectEx(&rc, style, true, WS_EX_COMPOSITED);	

	hWnd = CreateWindowEx(WS_EX_COMPOSITED, CLASS_NAME,
				L"PUMA 6C", style, CW_USEDEFAULT, 
				CW_USEDEFAULT, rc.right - rc.left, 
				rc.bottom - rc.top, 0, 0, hInst, 0);

	OnInit();

	//hTools = CreateToolBar();
	//ShowWindow(hWnd, SW_SHOW);
	//UpdateWindow(hWnd);
}

int BaseWindow::Run() {
	MSG msg; 
	msg.message = WM_NULL;

	while(msg.message != WM_QUIT) {
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
			if (!IsDialogMessage(hWnd, &msg)) {
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		} else {
			if(this->activate) {
				Draw();
				SwapBuffers(hDC);
			}
		}
	}
	return static_cast<int> (msg.wParam);
}

void CALLBACK BaseWindow::TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) {
	//return single->OnTimer(hwnd, uMsg, idEvent, dwTime);
	single->OnTimerMethod();
}

LRESULT CALLBACK BaseWindow::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	return single->OnWndProc(hWnd, msg, wParam, lParam);
}

LRESULT BaseWindow::OnWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	POINT pp;
	switch(msg) {
	case WM_KEYDOWN:
 		OnKeyDown(wParam);
		break;
	case WM_LBUTTONDOWN:
		point = MAKEPOINTS(lParam);
		OnLButtonDown(wParam, lParam);
		break;
	case WM_COMMAND:
		OnMenuChoosed(wParam);
		break;
	case WM_RBUTTONDOWN:	
		point = MAKEPOINTS(lParam);
		if((wParam & MK_CONTROL) == 0)
			OnRButtonDown(wParam, lParam);
		break;
	case WM_MOUSEWHEEL:		
		OnMouseWheel(wParam, lParam);
		break;
	case WM_RBUTTONUP:
		break;
	case WM_LBUTTONUP:		
		break;
	case WM_MOUSEMOVE:
		if( ((wParam & MK_CONTROL) != 0) && ((wParam & MK_RBUTTON) != 0) ) {
			pp.x = LOWORD(lParam);
			pp.y = HIWORD(lParam);
			ClientToScreen(hWnd, &pp);
			SetWindowPos(hWnd, HWND_TOPMOST, pp.x - point.x , pp.y - point.y , 0, 0, SWP_NOSIZE);
		}		
		OnMouseMove(wParam, lParam);
		break;
	case WM_SYSCOMMAND:
		switch (wParam)
		{
			case SC_SCREENSAVE:
			case SC_MONITORPOWER:
			return 0;
		}
		break;
	case WM_ACTIVATE:
		if (!HIWORD(wParam))
			this->activate = true;			
		else
			this->activate = false;
		return 0;
	case WM_ERASEBKGND:
		break;
	case WM_PAINT:
		//Draw();
		break;
	case WM_ENTERSIZEMOVE:
		return 0;
		break;
	case WM_CREATE:
		break;
	//case WM_WINDOWPOSCHANGED:
	//case WM_EXITSIZEMOVE:
	case WM_SIZE:
		ResizeWindow();
		SizeChanged();		
		break;
	case WM_DESTROY:
		OnDestroy();
		PostQuitMessage(0);
		break;
	default:
		break;
	}

	return DefWindowProc(hWnd, msg, wParam, lParam);
}

void BaseWindow::ResizeWindow() {
	RECT rc;
	GetClientRect(hWnd, &rc);
	wndWidth = static_cast<UINT>(rc.right - rc.left);
	wndHeight = static_cast<UINT>(rc.bottom - rc.top);
	if(hTools)
		SetWindowPos(hTools, HWND_TOPMOST, 0, 0, 
			rc.right-rc.left, toolHeight, SWP_SHOWWINDOW);
}

BaseWindow::BaseWindow(HINSTANCE hInst) {

	if(single == NULL)
		single = this;

	this->activate = true;
	this->fullScreen = false;
	this->wndHeight = 600;
	this->wndWidth = 800;
	this->toolHeight = 0;
	this->hInst = hInst;
	this->hWnd = NULL;
	this->hDC = NULL;
	this->hRC = NULL;
	this->hTools = NULL;
	this->hToolBmp = NULL;
}

BaseWindow::~BaseWindow() {
	if(hToolBmp)
		DeleteObject(hToolBmp);
	if(!UnregisterClass(CLASS_NAME, hInst)) {
		MessageBox(NULL, L"Could Not Unregister Class.",
			L"SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
		hInst=NULL;				
	}
}

int BaseWindow::Go(HICON hicon) {
	INITCOMMONCONTROLSEX icsex;
	icsex.dwSize = sizeof(INITCOMMONCONTROLSEX);
	icsex.dwICC = ICC_COOL_CLASSES|ICC_BAR_CLASSES;
	InitCommonControlsEx(&icsex);
	
	this->CreateWndClass(hicon);
	this->CreateWnd();
	this->OnCreate();
	return this->Run();
}

void BaseWindow::Exit() {
	PostMessage(hWnd, WM_CLOSE, 0, 0);
}